package com.imis.module.system.bus;

import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.imis.base.constant.enums.ArgumentResponseEnum;
import com.imis.base.globle.response.BaseResponse;
import com.imis.base.globle.response.CommonResponse;
import com.imis.module.base.BaseBus;
import com.imis.module.system.model.converter.SysRoleConverter;
import com.imis.module.system.model.po.SysMenu;
import com.imis.module.system.model.po.SysRole;
import com.imis.module.system.model.po.SysUser;
import com.imis.module.system.model.ro.*;
import com.imis.module.system.model.vo.SysRoleVO;
import com.imis.module.system.model.vo.SysUserVO;
import com.imis.module.system.service.ISysMenuService;
import com.imis.module.system.service.ISysRoleService;
import com.imis.module.system.service.ISysUserRoleService;
import com.imis.module.system.service.ISysUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.List;

/**
 * <p>
 * 系统角色表-权限组 业务处理类
 * </p>
 *
 * @author XinLau
 * @since 2020-03-12
 */
@Service
public class SysRoleBus extends BaseBus {

    /**
     * 系统角色表-权限组 服务类
     */
    private ISysRoleService serviceBySysRoleService;

    @Autowired
    public void setServiceBySysRoleService(ISysRoleService serviceBySysRoleService) {
        this.serviceBySysRoleService = serviceBySysRoleService;
    }

    /**
     * 功能菜单表 服务类
     */
    private ISysMenuService serviceBySysMenuService;

    @Autowired
    public void setServiceBySysMenuService(ISysMenuService serviceBySysMenuService) {
        this.serviceBySysMenuService = serviceBySysMenuService;
    }

    /**
     * 用户角色关联表 服务类
     */
    private ISysUserRoleService sysUserRoleService;

    @Autowired
    public void setSysUserRoleService(ISysUserRoleService sysUserRoleService) {
        this.sysUserRoleService = sysUserRoleService;
    }

    /**
     * 用户信息 服务类
     */
    private ISysUserService sysUserService;

    @Autowired
    public void setSysUserService(ISysUserService sysUserService) {
        this.sysUserService = sysUserService;
    }

    /**
     * 添加角色校验
     *
     * @param sysRoleAdd - 角色
     * @return SysRole - 角色
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    private SysRole roleAddVerification(final SysRoleAddRO sysRoleAdd) {
        SysRole sysRole = this.serviceBySysRoleService.queryRoleByName(sysRoleAdd.getRoleName());
        // 1.判断角色是否存在
        ArgumentResponseEnum.ROLE_ADD_ERR_NAME_REPEAT.assertNotNull(sysRole, sysRoleAdd.getRoleName());
        sysRole = this.serviceBySysRoleService.queryRoleByCode(sysRoleAdd.getRoleCode());
        // 2.判断角色编码是否存在
        ArgumentResponseEnum.ROLE_ADD_ERR_CODE_REPEAT.assertNotNull(sysRole, sysRoleAdd.getRoleCode());
        return SysRoleConverter.INSTANCE.getAddEntity(sysRoleAdd);
    }

    /**
     * 删除角色校验
     *
     * @param roleIdentification - 角色编号
     * @return SysRole - 角色
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    private SysRole roleDeleteVerification(final Long roleIdentification) {
        SysRole sysRole = this.serviceBySysRoleService.getById(roleIdentification);
        // 1.判断角色是否存在
        ArgumentResponseEnum.ROLE_DELETE_ERR_NON.assertNotNull(sysRole, roleIdentification);
        // 2.判断角色是否分配给用户
        List<Long> sysUserIdList = this.serviceBySysRoleService.selectSysUserIdArrayByRoleId(sysRole.getId());
        ArgumentResponseEnum.ROLE_DELETE_ERR_ASSIGNED.assertNotEmpty(sysUserIdList, sysRole.getRoleName(), JSONUtil.toJsonStr(sysUserIdList));
        return sysRole;
    }

    /**
     * 更新角色校验
     *
     * @param sysRoleUpdate - 角色
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    private SysRole roleUpdateVerification(final SysRoleUpdateRO sysRoleUpdate) {
        SysRole sysRole = this.serviceBySysRoleService.getById(sysRoleUpdate.getId());
        // 1.根据角色信息查询，该角色不存在
        ArgumentResponseEnum.ROLE_UPDATE_ERR_NON.assertNotNull(sysRole, sysRoleUpdate.getRoleName());
        // 2.校验角色名重复
        if (!sysRole.getRoleName().equals(sysRoleUpdate.getRoleName())) {
            // 前端传递角色名与数据库查询出来的不一致做角色名重复校验（角色名修改做校验）
            SysRole sysRoleByName = this.serviceBySysRoleService.queryRoleByName(sysRoleUpdate.getRoleName());
            //  根据角色名查询，该角色名存在
            ArgumentResponseEnum.ROLE_UPDATE_ERR_NAME_REPEAT.assertIsNull(sysRoleByName, sysRoleUpdate.getRoleName());
        }
        // 3.角色编码重复校验
        if (!sysRole.getRoleCode().equals(sysRoleUpdate.getRoleCode())) {
            SysRole sysRoleByCode = this.serviceBySysRoleService.queryRoleByCode(sysRoleUpdate.getRoleCode());
            //  根据角色编码查询，该角色编码存在
            ArgumentResponseEnum.ROLE_UPDATE_ERR_CODE_REPEAT.assertIsNull(sysRoleByCode, sysRoleUpdate.getRoleCode());
        }
        SysRoleConverter.INSTANCE.getUpdateEntity(sysRole, sysRoleUpdate);
        return sysRole;
    }

    /**
     * 为角色授权功能菜单权限检验
     *
     * @param sysGrantMenuPermissionToRole - 角色授权功能菜单
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/21 11:05
     */
    private void grantMenuPermissionsToRoleVerification(final SysGrantMenuPermissionToRoleRO sysGrantMenuPermissionToRole) {
        // 1.验证角色合法性
        Long roleId = sysGrantMenuPermissionToRole.getRoleId();
        SysRole sysRole = this.serviceBySysRoleService.getById(roleId);
        ArgumentResponseEnum.GRANT_MENU_TO_ROLE_ERR_NON_ROLE.assertNotNull(sysRole, roleId);
        // 2.验证功能菜单的合法性
        List<Long> menuIdList = sysGrantMenuPermissionToRole.getMenuIdList();
        List<SysMenu> sysMenuList = this.serviceBySysMenuService.listByIds(menuIdList);
        ArgumentResponseEnum.GRANT_MENU_TO_ROLE_ERR_NON_MENU.assertIsTrue(menuIdList.size() == sysMenuList.size(), JSONUtil.toJsonStr(menuIdList));
    }

    /**
     * 角色授权用户校验
     *
     * @param sysGrantRoleToUsers - 角色授权用户
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:18
     */
    private void grantRoleToUsersVerification(final SysGrantRoleToUsersRO sysGrantRoleToUsers) {
        // 1.验证角色合法性
        Long roleId = sysGrantRoleToUsers.getRoleId();
        SysRole sysRole = this.serviceBySysRoleService.getById(roleId);
        ArgumentResponseEnum.AUTHORIZING_ROLE_TO_USERS_ERR_NON_ROLE.assertNotNull(sysRole, roleId);
        // 2.验证用户合法性
        List<Long> userIdList = sysGrantRoleToUsers.getUserIdList();
        List<SysUser> sysUserList = this.sysUserService.listByIds(userIdList);
        ArgumentResponseEnum.AUTHORIZING_ROLE_TO_USERS_ERR_NON_USER.assertIsTrue(userIdList.size() == sysUserList.size(), JSONUtil.toJsonStr(userIdList));
    }

    /**
     * 取消角色授权用户校验
     *
     * @param sysUnGrantRoleToUsers - 取消角色授权用户
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 14:18
     */
    private void unGrantRoleToUsersVerification(final SysUnGrantRoleToUsersRO sysUnGrantRoleToUsers) {
        // 1.验证角色合法性
        Long roleId = sysUnGrantRoleToUsers.getRoleId();
        SysRole sysRole = this.serviceBySysRoleService.getById(roleId);
        ArgumentResponseEnum.UN_AUTHORIZING_ROLE_TO_USERS_ERR_NON_ROLE.assertNotNull(sysRole, roleId);
        // 2.验证用户合法性
        List<Long> userIdList = sysUnGrantRoleToUsers.getUserIdList();
        List<SysUser> sysUserList = this.sysUserService.listByIds(userIdList);
        ArgumentResponseEnum.AUTHORIZING_ROLE_TO_USERS_ERR_NON_USER.assertIsTrue(userIdList.size() == sysUserList.size(), JSONUtil.toJsonStr(userIdList));
    }

    /**
     * 分页查询角色信息
     *
     * @param pagingQueryRoleDTO - 角色信息查询对象
     * @return Result
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/9 9:47
     */
    public CommonResponse<Page<SysRoleVO>> pagingQuerySysRoleListByParameter(final PagingQueryRoleDTO pagingQueryRoleDTO) {
        Page<SysRoleVO> sysRoleSelectPage = this.serviceBySysRoleService.pagingQuerySysRoleListByParameter(pagingQueryRoleDTO);
        return new CommonResponse(sysRoleSelectPage);
    }

    /**
     * 创建角色
     *
     * @param sysRoleAdd - 角色添加对象
     * @return Result - 角色对象
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:26
     */
    public BaseResponse addRole(SysRoleAddRO sysRoleAdd) {
        // 1.校验角色重复
        SysRole sysRole = this.roleAddVerification(sysRoleAdd);
        // 2.创建新角色
        boolean saveRole = this.serviceBySysRoleService.saveRole(sysRole);
        // 判断保存成功
        ArgumentResponseEnum.ROLE_ADD_ERR.assertIsTrue(saveRole, sysRoleAdd.getRoleName());
        return new CommonResponse<>();
    }

    /**
     * 删除角色
     *
     * @param roleIdentification - 角色标识
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:26
     */
    public BaseResponse deleteRole(final Long roleIdentification) {
        // 1.删除角色校验
        SysRole sysRole = this.roleDeleteVerification(roleIdentification);
        // 2.清除角色分配的权限
        boolean cleanRolePermissionsById = this.serviceBySysRoleService.cleanRolePermissionsById(roleIdentification);
        ArgumentResponseEnum.ROLE_ADD_ERR.assertIsTrue(cleanRolePermissionsById, sysRole.getRoleName());
        // 3.删除角色
        boolean deleteRole = this.serviceBySysRoleService.deleteRole(roleIdentification);
        ArgumentResponseEnum.ROLE_DELETE_ERR.assertIsTrue(cleanRolePermissionsById, sysRole.getRoleName());
        // TODO:this 删除对应角色的权限缓存
        return new CommonResponse<>();
    }

    /**
     * 查看角色
     *
     * @param roleIdentification - 角色标识
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:26
     */
    public CommonResponse<SysRoleVO> queryRoleById(final Long roleIdentification) {
        SysRole sysRole = this.serviceBySysRoleService.getById(roleIdentification);
        ArgumentResponseEnum.ROLE_QUERY_ERR.assertNotNull(sysRole);
        return new CommonResponse<>(SysRoleConverter.INSTANCE.getReturnValue(sysRole));
    }

    /**
     * 根据角色标识查看用户
     *
     * @param pagingQueryUserByRoleIdDTO - 根据角色查询用户对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:26
     */
    public CommonResponse<Page<SysUserVO>> pagingQuerySysUserListByRoleIdParameter(final PagingQueryUserByRoleIdDTO pagingQueryUserByRoleIdDTO) {
        SysRole sysRole = this.serviceBySysRoleService.getById(pagingQueryUserByRoleIdDTO.getRoleId());
        // 判断角色是否存在
        ArgumentResponseEnum.ROLE_QUERY_ERR.assertNotNull(sysRole);
        Page<SysUserVO> sysUserList = this.sysUserRoleService.pagingQuerySysUserListByRoleIdParameter(pagingQueryUserByRoleIdDTO);
        return new CommonResponse<>(sysUserList);
    }

    /**
     * 根据角色标识查看未授权用户
     *
     * @param pagingQueryUserByRoleIdDTO - 根据角色查询用户对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:26
     */
    public CommonResponse<Page<SysUserVO>> pagingQueryUnauthorizedSysUserListByRoleIdParameter(final PagingQueryUserByRoleIdDTO pagingQueryUserByRoleIdDTO) {
        SysRole sysRole = this.serviceBySysRoleService.getById(pagingQueryUserByRoleIdDTO.getRoleId());
        // 判断角色是否存在
        ArgumentResponseEnum.ROLE_QUERY_ERR.assertNotNull(sysRole);
        Page<SysUserVO> sysUserList = this.sysUserRoleService.pagingQueryUnauthorizedSysUserListByRoleIdParameter(pagingQueryUserByRoleIdDTO);
        return new CommonResponse<>(sysUserList);
    }

    /**
     * 修改角色
     *
     * @param sysRoleUpdate - 角色修改对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/12 17:26
     */
    public BaseResponse updateRole(SysRoleUpdateRO sysRoleUpdate) {
        // 1.修改角色校验
        SysRole sysRole = this.roleUpdateVerification(sysRoleUpdate);
        // 2.角色信息修改
        boolean updateRole = this.serviceBySysRoleService.updateByRoleIdentification(sysRole);
        // 3.判断保存成功
        ArgumentResponseEnum.ROLE_UPDATE_ERR.assertIsTrue(updateRole, sysRole.getRoleName());
        return new CommonResponse<>();
    }

    /**
     * 分页查找已授权角色
     *
     * @param sysUserRoleSelect - 授权角色查询对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 15:33
     */
    public CommonResponse<Page<SysRoleVO>> pagingQueryGrantRoleListByParameter(final PagingQueryUserRoleDTO sysUserRoleSelect) {
        Page<SysRoleVO> sysRoleSelectPage = this.serviceBySysRoleService.pagingQueryGrantRoleListByParameter(sysUserRoleSelect);
        return new CommonResponse<>(sysRoleSelectPage);
    }

    /**
     * 分页查询未授权角色
     *
     * @param sysUserRoleSelect - 授权角色查询对象
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/20 15:33
     */
    public CommonResponse<Page<SysRoleVO>> pagingQueryNotGrantRoleListByParameter(final PagingQueryUserRoleDTO sysUserRoleSelect) {
        Page<SysRoleVO> sysRoleSelectPage = this.serviceBySysRoleService.pagingQueryNotGrantRoleListByParameter(sysUserRoleSelect);
        return new CommonResponse<>(sysRoleSelectPage);
    }

    /**
     * 为角色授权功能菜单权限
     *
     * @param sysGrantMenuPermissionToRole - 角色授权功能菜单
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/21 10:59
     */
    public BaseResponse grantMenuPermissionsToRole(SysGrantMenuPermissionToRoleRO sysGrantMenuPermissionToRole) {
        // 1.为角色授权功能菜单权限检验
        this.grantMenuPermissionsToRoleVerification(sysGrantMenuPermissionToRole);
        // 2.授权操作
        boolean grant = this.serviceBySysRoleService.grantMenuPermissionsToRole(sysGrantMenuPermissionToRole);
        ArgumentResponseEnum.GRANT_MENU_TO_ROLE_ERR.assertIsTrue(grant, sysGrantMenuPermissionToRole.getRoleId());
        return new CommonResponse<>();
    }

    /**
     * 撤销角色功能菜单权限
     *
     * @param roleId - 角色编号
     * @return Result -
     * @author XinLau
     * @creed The only constant is change ! ! !
     * @since 2020/3/21 13:45
     */
    public BaseResponse terminateAllMenuPermissionsToRole(final Long roleId) {
        // 1.验证角色合法性
        SysRole sysRole = this.serviceBySysRoleService.getById(roleId);
        ArgumentResponseEnum.TERMINATE_ALL_MENU_TO_ROLE_ERR_NON_ROLE.assertNotNull(sysRole, roleId);
        // 2.撤销授权
        boolean terminate = this.serviceBySysRoleService.cleanRolePermissionsById(roleId);
        ArgumentResponseEnum.TERMINATE_ALL_MENU_TO_ROLE_ERR.assertIsTrue(terminate, roleId);
        return new CommonResponse<>();
    }

    /**
     * 角色授权用户
     *
     * @param sysGrantRoleToUsers - 角色授权用户
     * @return Result -
     * @creed The only constant is change ! ! !
     * @since 2020/7/3 13:45
     */
    public BaseResponse authorizingRoleToUsers(final SysGrantRoleToUsersRO sysGrantRoleToUsers) {
        // 1.角色授权用户校验
        this.grantRoleToUsersVerification(sysGrantRoleToUsers);
        // 2.授权操作
        boolean grant = this.sysUserRoleService.authorizingRoleToUsers(sysGrantRoleToUsers);
        ArgumentResponseEnum.AUTHORIZING_ROLE_TO_USERS_ERR.assertIsTrue(grant, sysGrantRoleToUsers.getRoleId());
        return new CommonResponse<>();
    }

    /**
     * 取消角色授权用户
     *
     * @param sysUnGrantRoleToUsers - 取消角色授权用户
     * @return Result -
     * @creed The only constant is change ! ! !
     * @since 2020/7/3 13:45
     */
    public BaseResponse unAuthorizingRoleToUsers(final SysUnGrantRoleToUsersRO sysUnGrantRoleToUsers) {
        // 1.角色授权用户校验
        this.unGrantRoleToUsersVerification(sysUnGrantRoleToUsers);
        // 2.授权操作
        boolean unGrant = this.sysUserRoleService.unAuthorizingRoleToUsers(sysUnGrantRoleToUsers);
        ArgumentResponseEnum.TERMINATE_ALL_MENU_TO_ROLE_ERR.assertIsTrue(unGrant, sysUnGrantRoleToUsers.getRoleId());
        return new CommonResponse<>();
    }

}